package com.qianyucc.blog.service;

import com.google.common.collect.*;
import com.qianyucc.blog.mapper.*;
import com.qianyucc.blog.model.entity.*;
import com.qianyucc.blog.model.pojo.*;
import com.qianyucc.blog.model.vo.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.transaction.annotation.*;

import java.time.*;
import java.util.*;

/**
 * @author lijing
 * @date 2019-10-16 11:02
 * @description 博客整体业务
 */
@Service
public class BlogService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private ArticleService articleService;
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ConfigMapper configMapper;
    @Autowired
    private Configs configs;

    /**
     * 导出博客所有数据
     *
     * @return 博客所有数据对象
     */
    public BlogData export() {
        BlogData blogData = BlogData.builder()
                .articleDOS(articleMapper.findAll())
                .commentDOS(commentMapper.findAll())
                .messageDOS(messageMapper.findAll())
                .userDOS(userMapper.findAll())
                .configDOS(configMapper.findAll())
                .build();
        return blogData;
    }

    /**
     * 获取博客信息
     *
     * @return 博客信息
     */
    public BlogInfoVO getBlogInfo() {
        BlogInfoVO blogInfoVO = new BlogInfoVO();
        blogInfoVO.setArticlesCount(articleMapper.countByCondition(null));
        blogInfoVO.setTotalViews(articleMapper.countViews());
        blogInfoVO.setTotalComments(commentMapper.count());
        blogInfoVO.setTotalTags((long) articleService.findAllTags().size());
        blogInfoVO.setBlogName(configs.getBlogName());
        blogInfoVO.setBlogDesc(configs.getBlogDesc());
        blogInfoVO.setBlogIcon(configs.getBlogIcon());
        return blogInfoVO;
    }

    /**
     * 半年内文章数统计（生成图表数据）
     *
     * @return 文章数统计
     */
    public Map<String, Object> countByMonth() {
        Map<String, Object> map = new HashMap<>();
        List<String> xAxis = new ArrayList<>();
        List<Long> counts = new ArrayList<>();
        LocalDate date = LocalDate.now();
        for (int i = 0; i < 6; i++) {
            xAxis.add(date.getMonthValue() + "月");
            counts.add(getArticlesCount(date));
            date = date.minusMonths(1);
        }
        map.put("xAxis", Lists.reverse(xAxis));
        map.put("counts", Lists.reverse(counts));
        return map;
    }

    /**
     * 计算指定月份的文章数
     *
     * @param date 要统计的月份
     * @return 该月份文章数
     */
    private long getArticlesCount(LocalDate date) {
        HashMap<String, Object> map = new HashMap<>();
        LocalDateTime thisMonth = LocalDateTime.of(date.getYear(), date.getMonth(), 1, 0, 0);
        LocalDateTime nextMonth = thisMonth.plusMonths(1);
        map.put("month", thisMonth.toInstant(ZoneOffset.of("+8")).toEpochMilli());
        map.put("nextMonth", nextMonth.toInstant(ZoneOffset.of("+8")).toEpochMilli());
        return articleMapper.countByCondition(map);
    }

    /**
     * 恢复博客数据
     *
     * @param blogData 博客全部数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void importData(BlogData blogData) {
        List<ArticleDO> articleDOS = blogData.getArticleDOS();
        List<CommentDO> commentDOS = blogData.getCommentDOS();
        List<MessageDO> messageDOS = blogData.getMessageDOS();
        List<UserDO> userDOS = blogData.getUserDOS();
        List<ConfigDO> configDOS = blogData.getConfigDOS();

        articleDOS.forEach(articleDO -> {
            ArticleDO article = articleMapper.findById(articleDO.getId());
            if (article == null) {
                articleMapper.insArticle(articleDO);
            } else {
                articleMapper.updArticle(articleDO);
            }
        });
        commentDOS.forEach(commentDO -> {
            CommentDO comment = commentMapper.findById(commentDO.getId());
            if (comment != null) {
                commentMapper.deleteById(comment.getId());
            }
            commentMapper.insComment(commentDO);
        });
        messageDOS.forEach(messageDO -> {
            MessageDO message = messageMapper.findById(messageDO.getId());
            if (message != null) {
                messageMapper.deleteById(messageDO.getId());
            }
            messageMapper.insMessage(messageDO);
        });
        userDOS.forEach(userDO -> {
            UserDO user = userMapper.findById(userDO.getId());
            if (user == null) {
                userMapper.insUser(userDO);
            } else {
                userMapper.updUser(userDO);
            }
        });
        configDOS.forEach(configDO -> {
            ConfigDO config = configMapper.findByKey(configDO.getKey());
            // 如果有值的话，说明在初始化的时候设置了新的值，就不必更新了
            if (config != null && (config.getValue() == null || "".equals(config.getValue()))) {
                configMapper.update(configDO);
            } else {
                configMapper.insert(configDO);
            }
        });
        configs.fromList(configMapper.findAll());
    }
}
